home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gsparam.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  12.1 KB  |  462 lines

  1. /* Copyright (C) 1995, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gsparam.c,v 1.4 2000/09/19 19:00:30 lpd Exp $ */
  20. /* Support for parameter lists */
  21. #include "memory_.h"
  22. #include "string_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gsparam.h"
  26. #include "gsstruct.h"
  27.  
  28. /* GC procedures */
  29. ENUM_PTRS_WITH(gs_param_typed_value_enum_ptrs, gs_param_typed_value *pvalue) return 0;
  30.     case 0:
  31.     switch (pvalue->type) {
  32.     case gs_param_type_string:
  33.     return ENUM_STRING(&pvalue->value.s);
  34.     case gs_param_type_name:
  35.     return ENUM_STRING(&pvalue->value.n);
  36.     case gs_param_type_int_array:
  37.     return ENUM_OBJ(pvalue->value.ia.data);
  38.     case gs_param_type_float_array:
  39.     return ENUM_OBJ(pvalue->value.fa.data);
  40.     case gs_param_type_string_array:
  41.     return ENUM_OBJ(pvalue->value.sa.data);
  42.     case gs_param_type_name_array:
  43.     return ENUM_OBJ(pvalue->value.na.data);
  44.     default:
  45.     return ENUM_OBJ(0);    /* don't stop early */
  46.     }
  47. ENUM_PTRS_END
  48. RELOC_PTRS_WITH(gs_param_typed_value_reloc_ptrs, gs_param_typed_value *pvalue) {
  49.     switch (pvalue->type) {
  50.     case gs_param_type_string:
  51.     case gs_param_type_name: {
  52.     gs_const_string str;
  53.  
  54.     str.data = pvalue->value.s.data; /* n == s */
  55.     str.size = pvalue->value.s.size;
  56.     RELOC_CONST_STRING_VAR(str);
  57.     pvalue->value.s.data = str.data;
  58.     break;
  59.     }
  60.     case gs_param_type_int_array:
  61.     RELOC_VAR(pvalue->value.ia.data);
  62.     break;
  63.     case gs_param_type_float_array:
  64.     RELOC_VAR(pvalue->value.fa.data);
  65.     break;
  66.     case gs_param_type_string_array:
  67.     RELOC_VAR(pvalue->value.sa.data);
  68.     break;
  69.     case gs_param_type_name_array:
  70.     RELOC_VAR(pvalue->value.na.data);
  71.     break;
  72.     default:
  73.     break;
  74.     }
  75. }
  76. RELOC_PTRS_END
  77.  
  78. /* Internal procedure to initialize the common part of a parameter list. */
  79. void
  80. gs_param_list_init(gs_param_list *plist, const gs_param_list_procs *procs,
  81.            gs_memory_t *mem)
  82. {
  83.     plist->procs = procs;
  84.     plist->memory = mem;
  85.     plist->persistent_keys = true;
  86. }
  87.  
  88. /* Set whether the keys for param_write_XXX are persistent. */
  89. void
  90. gs_param_list_set_persistent_keys(gs_param_list *plist, bool persistent)
  91. {
  92.     plist->persistent_keys = persistent;
  93. }
  94.  
  95. /* Reset a gs_param_key_t enumerator to its initial state */
  96. void
  97. param_init_enumerator(gs_param_enumerator_t * enumerator)
  98. {
  99.     memset(enumerator, 0, sizeof(*enumerator));
  100. }
  101.  
  102. /* Transfer a collection of parameters. */
  103. private const byte xfer_item_sizes[] = {
  104.     GS_PARAM_TYPE_SIZES(0)
  105. };
  106. int
  107. gs_param_read_items(gs_param_list * plist, void *obj,
  108.             const gs_param_item_t * items)
  109. {
  110.     const gs_param_item_t *pi;
  111.     int ecode = 0;
  112.  
  113.     for (pi = items; pi->key != 0; ++pi) {
  114.     const char *key = pi->key;
  115.     void *pvalue = (void *)((char *)obj + pi->offset);
  116.     gs_param_typed_value typed;
  117.     int code;
  118.  
  119.     typed.type = pi->type;
  120.     code = param_read_requested_typed(plist, key, &typed);
  121.     switch (code) {
  122.         default:        /* < 0 */
  123.         ecode = code;
  124.         case 1:
  125.         break;
  126.         case 0:
  127.         if (typed.type != pi->type)    /* shouldn't happen! */
  128.             ecode = gs_note_error(gs_error_typecheck);
  129.         else
  130.             memcpy(pvalue, &typed.value, xfer_item_sizes[pi->type]);
  131.     }
  132.     }
  133.     return ecode;
  134. }
  135. int
  136. gs_param_write_items(gs_param_list * plist, const void *obj,
  137.              const void *default_obj, const gs_param_item_t * items)
  138. {
  139.     const gs_param_item_t *pi;
  140.     int ecode = 0;
  141.  
  142.     for (pi = items; pi->key != 0; ++pi) {
  143.     const char *key = pi->key;
  144.     const void *pvalue = (const void *)((const char *)obj + pi->offset);
  145.     int size = xfer_item_sizes[pi->type];
  146.     gs_param_typed_value typed;
  147.     int code;
  148.  
  149.     if (default_obj != 0 &&
  150.         !memcmp((const void *)((const char *)default_obj + pi->offset),
  151.             pvalue, size)
  152.         )
  153.         continue;
  154.     memcpy(&typed.value, pvalue, size);
  155.     typed.type = pi->type;
  156.     code = (*plist->procs->xmit_typed) (plist, key, &typed);
  157.     if (code < 0)
  158.         ecode = code;
  159.     }
  160.     return ecode;
  161. }
  162.  
  163. /* Read a value, with coercion if requested, needed, and possible. */
  164. /* If mem != 0, we can coerce int arrays to float arrays. */
  165. int
  166. param_coerce_typed(gs_param_typed_value * pvalue, gs_param_type req_type,
  167.            gs_memory_t * mem)
  168. {
  169.     if (req_type == gs_param_type_any || pvalue->type == req_type)
  170.     return 0;
  171.     /*
  172.      * Look for coercion opportunities.  It would be wonderful if we
  173.      * could convert int/float arrays and name/string arrays, but
  174.      * right now we can't.  However, a 0-length heterogenous array
  175.      * will satisfy a request for any specific type.
  176.      */
  177.     switch (pvalue->type /* actual type */ ) {
  178.     case gs_param_type_int:
  179.         switch (req_type) {
  180.         case gs_param_type_long:
  181.             pvalue->value.l = pvalue->value.i;
  182.             goto ok;
  183.         case gs_param_type_float:
  184.             pvalue->value.f = (float)pvalue->value.l;
  185.             goto ok;
  186.         default:
  187.             break;
  188.         }
  189.         break;
  190.     case gs_param_type_long:
  191.         switch (req_type) {
  192.         case gs_param_type_int:
  193. #if arch_sizeof_int < arch_sizeof_long
  194.             if (pvalue->value.l != (int)pvalue->value.l)
  195.             return_error(gs_error_rangecheck);
  196. #endif
  197.             pvalue->value.i = (int)pvalue->value.l;
  198.             goto ok;
  199.         case gs_param_type_float:
  200.             pvalue->value.f = (float)pvalue->value.l;
  201.             goto ok;
  202.         default:
  203.             break;
  204.         }
  205.         break;
  206.     case gs_param_type_string:
  207.         if (req_type == gs_param_type_name)
  208.         goto ok;
  209.         break;
  210.     case gs_param_type_name:
  211.         if (req_type == gs_param_type_string)
  212.         goto ok;
  213.         break;
  214.     case gs_param_type_int_array:
  215.         switch (req_type) {
  216.         case gs_param_type_float_array:{
  217.             uint size = pvalue->value.ia.size;
  218.             float *fv;
  219.             uint i;
  220.  
  221.             if (mem == 0)
  222.                 break;
  223.             fv = (float *)gs_alloc_byte_array(mem, size, sizeof(float),
  224.                         "int array => float array");
  225.  
  226.             if (fv == 0)
  227.                 return_error(gs_error_VMerror);
  228.             for (i = 0; i < size; ++i)
  229.                 fv[i] = pvalue->value.ia.data[i];
  230.             pvalue->value.fa.data = fv;
  231.             pvalue->value.fa.persistent = false;
  232.             goto ok;
  233.             }
  234.         default:
  235.             break;
  236.         }
  237.         break;
  238.     case gs_param_type_string_array:
  239.         if (req_type == gs_param_type_name_array)
  240.         goto ok;
  241.         break;
  242.     case gs_param_type_name_array:
  243.         if (req_type == gs_param_type_string_array)
  244.         goto ok;
  245.         break;
  246.     case gs_param_type_array:
  247.         if (pvalue->value.d.size == 0 &&
  248.         (req_type == gs_param_type_int_array ||
  249.          req_type == gs_param_type_float_array ||
  250.          req_type == gs_param_type_string_array ||
  251.          req_type == gs_param_type_name_array)
  252.         )
  253.         goto ok;
  254.         break;
  255.     default:
  256.         break;
  257.     }
  258.     return_error(gs_error_typecheck);
  259.   ok:pvalue->type = req_type;
  260.     return 0;
  261. }
  262. int
  263. param_read_requested_typed(gs_param_list * plist, gs_param_name pkey,
  264.                gs_param_typed_value * pvalue)
  265. {
  266.     gs_param_type req_type = pvalue->type;
  267.     int code = (*plist->procs->xmit_typed) (plist, pkey, pvalue);
  268.  
  269.     if (code != 0)
  270.     return code;
  271.     return param_coerce_typed(pvalue, req_type, plist->memory);
  272. }
  273.  
  274.  
  275. /* ---------------- Fixed-type reading procedures ---------------- */
  276.  
  277. #define RETURN_READ_TYPED(alt, ptype)\
  278.   gs_param_typed_value typed;\
  279.   int code;\
  280. \
  281.   typed.type = ptype;\
  282.   code = param_read_requested_typed(plist, pkey, &typed);\
  283.   if ( code == 0 )\
  284.     *pvalue = typed.value.alt;\
  285.   return code
  286.  
  287. int
  288. param_read_null(gs_param_list * plist, gs_param_name pkey)
  289. {
  290.     gs_param_typed_value typed;
  291.  
  292.     typed.type = gs_param_type_null;
  293.     return param_read_requested_typed(plist, pkey, &typed);
  294. }
  295. int
  296. param_read_bool(gs_param_list * plist, gs_param_name pkey, bool * pvalue)
  297. {
  298.     RETURN_READ_TYPED(b, gs_param_type_bool);
  299. }
  300. int
  301. param_read_int(gs_param_list * plist, gs_param_name pkey, int *pvalue)
  302. {
  303.     RETURN_READ_TYPED(i, gs_param_type_int);
  304. }
  305. int
  306. param_read_long(gs_param_list * plist, gs_param_name pkey, long *pvalue)
  307. {
  308.     RETURN_READ_TYPED(l, gs_param_type_long);
  309. }
  310. int
  311. param_read_float(gs_param_list * plist, gs_param_name pkey, float *pvalue)
  312. {
  313.     RETURN_READ_TYPED(f, gs_param_type_float);
  314. }
  315. int
  316. param_read_string(gs_param_list * plist, gs_param_name pkey,
  317.           gs_param_string * pvalue)
  318. {
  319.     RETURN_READ_TYPED(s, gs_param_type_string);
  320. }
  321. int
  322. param_read_name(gs_param_list * plist, gs_param_name pkey,
  323.         gs_param_string * pvalue)
  324. {
  325.     RETURN_READ_TYPED(n, gs_param_type_string);
  326. }
  327. int
  328. param_read_int_array(gs_param_list * plist, gs_param_name pkey,
  329.              gs_param_int_array * pvalue)
  330. {
  331.     RETURN_READ_TYPED(ia, gs_param_type_int_array);
  332. }
  333. int
  334. param_read_float_array(gs_param_list * plist, gs_param_name pkey,
  335.                gs_param_float_array * pvalue)
  336. {
  337.     RETURN_READ_TYPED(fa, gs_param_type_float_array);
  338. }
  339. int
  340. param_read_string_array(gs_param_list * plist, gs_param_name pkey,
  341.             gs_param_string_array * pvalue)
  342. {
  343.     RETURN_READ_TYPED(sa, gs_param_type_string_array);
  344. }
  345. int
  346. param_read_name_array(gs_param_list * plist, gs_param_name pkey,
  347.               gs_param_string_array * pvalue)
  348. {
  349.     RETURN_READ_TYPED(na, gs_param_type_name_array);
  350. }
  351.  
  352. #undef RETURN_READ_TYPED
  353.  
  354. /* ---------------- Default writing procedures ---------------- */
  355.  
  356. #define RETURN_WRITE_TYPED(alt, ptype)\
  357.   gs_param_typed_value typed;\
  358. \
  359.   typed.value.alt = *pvalue;\
  360.   typed.type = ptype;\
  361.   return param_write_typed(plist, pkey, &typed)
  362.  
  363. int
  364. param_write_null(gs_param_list * plist, gs_param_name pkey)
  365. {
  366.     gs_param_typed_value typed;
  367.  
  368.     typed.type = gs_param_type_null;
  369.     return param_write_typed(plist, pkey, &typed);
  370. }
  371. int
  372. param_write_bool(gs_param_list * plist, gs_param_name pkey, const bool * pvalue)
  373. {
  374.     RETURN_WRITE_TYPED(b, gs_param_type_bool);
  375. }
  376. int
  377. param_write_int(gs_param_list * plist, gs_param_name pkey, const int *pvalue)
  378. {
  379.     RETURN_WRITE_TYPED(i, gs_param_type_int);
  380. }
  381. int
  382. param_write_long(gs_param_list * plist, gs_param_name pkey, const long *pvalue)
  383. {
  384.     RETURN_WRITE_TYPED(l, gs_param_type_long);
  385. }
  386. int
  387. param_write_float(gs_param_list * plist, gs_param_name pkey,
  388.           const float *pvalue)
  389. {
  390.     RETURN_WRITE_TYPED(f, gs_param_type_float);
  391. }
  392. int
  393. param_write_string(gs_param_list * plist, gs_param_name pkey,
  394.            const gs_param_string * pvalue)
  395. {
  396.     RETURN_WRITE_TYPED(s, gs_param_type_string);
  397. }
  398. int
  399. param_write_name(gs_param_list * plist, gs_param_name pkey,
  400.          const gs_param_string * pvalue)
  401. {
  402.     RETURN_WRITE_TYPED(n, gs_param_type_name);
  403. }
  404. int
  405. param_write_int_array(gs_param_list * plist, gs_param_name pkey,
  406.               const gs_param_int_array * pvalue)
  407. {
  408.     RETURN_WRITE_TYPED(ia, gs_param_type_int_array);
  409. }
  410. int
  411. param_write_int_values(gs_param_list * plist, gs_param_name pkey,
  412.                const int *values, uint size, bool persistent)
  413. {
  414.     gs_param_int_array ia;
  415.  
  416.     ia.data = values, ia.size = size, ia.persistent = persistent;
  417.     return param_write_int_array(plist, pkey, &ia);
  418. }
  419. int
  420. param_write_float_array(gs_param_list * plist, gs_param_name pkey,
  421.             const gs_param_float_array * pvalue)
  422. {
  423.     RETURN_WRITE_TYPED(fa, gs_param_type_float_array);
  424. }
  425. int
  426. param_write_float_values(gs_param_list * plist, gs_param_name pkey,
  427.              const float *values, uint size, bool persistent)
  428. {
  429.     gs_param_float_array fa;
  430.  
  431.     fa.data = values, fa.size = size, fa.persistent = persistent;
  432.     return param_write_float_array(plist, pkey, &fa);
  433. }
  434. int
  435. param_write_string_array(gs_param_list * plist, gs_param_name pkey,
  436.              const gs_param_string_array * pvalue)
  437. {
  438.     RETURN_WRITE_TYPED(sa, gs_param_type_string_array);
  439. }
  440. int
  441. param_write_name_array(gs_param_list * plist, gs_param_name pkey,
  442.                const gs_param_string_array * pvalue)
  443. {
  444.     RETURN_WRITE_TYPED(na, gs_param_type_name_array);
  445. }
  446.  
  447. #undef RETURN_WRITE_TYPED
  448.  
  449. /* ---------------- Default request implementation ---------------- */
  450.  
  451. int
  452. gs_param_request_default(gs_param_list * plist, gs_param_name pkey)
  453. {
  454.     return 0;
  455. }
  456.  
  457. int
  458. gs_param_requested_default(const gs_param_list * plist, gs_param_name pkey)
  459. {
  460.     return -1;            /* requested by default */
  461. }
  462.